﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Contract;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace ConsoleApplication1
{
    class Program  
    {
        private static List<IPAddress> agentsIP = new List<IPAddress>();
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(Service_Allocation));

            NetTcpBinding binding = new NetTcpBinding();
            binding.TransferMode = TransferMode.Streamed;
            binding.ReceiveTimeout = TimeSpan.MaxValue;
            binding.MaxReceivedMessageSize = long.MaxValue;

            host.AddServiceEndpoint(typeof(IService_Allocation), binding,
            new Uri("net.tcp://127.0.0.1:8888/Service_Allocation"));

            host.Open();
            Thread.Sleep(5000);
            while (agentsIP.Count > 0)
            {
                Timer t = new Timer(Service_Allocation.ComputeBoundOp, null, 0, 10000);
            }

            Console.ReadKey();

        }


        public class Service_Allocation : IService_Allocation
        {
            //sort the list of ip
            public static void ComputeBoundOp(Object state)
            {
                if (agentsIP.Count != 0)
                {
                    NetTcpBinding binding = new NetTcpBinding();
                    binding.TransferMode = TransferMode.Streamed;
                    binding.MaxReceivedMessageSize = 200000000000000;
                    binding.SendTimeout = TimeSpan.MaxValue;
                    // Console.WriteLine()
                        string f = agentsIP[0].ToString();
                    EndpointAddress address = new EndpointAddress("net.tcp://" + agentsIP[0].ToString() + ":5000/DataUploader");
                    ChannelFactory<IDataUploader> channel =
                    new ChannelFactory<IDataUploader>(binding, address);
                    IDataUploader Proxy = channel.CreateChannel();
                    IPAddress targetAgent = agentsIP[0];
                    int con = Proxy.returnNumOfConnections();
                    foreach (IPAddress ip in agentsIP)
                    {
                        address = new EndpointAddress("net.tcp://" + ip.ToString() + ":5000/DataUploader");
                        channel = new ChannelFactory<IDataUploader>(binding, address);
                        Proxy = channel.CreateChannel();
                        if (con >= Proxy.returnNumOfConnections())
                        {
                            targetAgent = ip;
                        }
                        con = Proxy.returnNumOfConnections();
                    }
                    //   return targetAgent;
                }
            }

            // calculate the agent with least ip addres
            public IPAddress agentAllocation()
            {
                NetTcpBinding binding = new NetTcpBinding();
                binding.TransferMode = TransferMode.Streamed;
                binding.MaxReceivedMessageSize = 200000000000000;
                binding.SendTimeout = TimeSpan.MaxValue;
                EndpointAddress address = new EndpointAddress("net.tcp://" + agentsIP[0].ToString() + ":5000/DataUploader");
                ChannelFactory<IDataUploader> channel = new ChannelFactory<IDataUploader>(binding, address);
                IDataUploader Proxy = channel.CreateChannel();
                IPAddress targetAgent = agentsIP[0];
                int con = Proxy.returnNumOfConnections();

                foreach (IPAddress ip in agentsIP)
                {
                    address = new EndpointAddress("net.tcp://" + ip.ToString() + ":5000/DataUploader");
                    channel = new ChannelFactory<IDataUploader>(binding, address);
                    Proxy = channel.CreateChannel();

                    if (con >= Proxy.returnNumOfConnections())
                    {
                        targetAgent = ip;
                    }
                    con = Proxy.returnNumOfConnections();

                }
                return targetAgent;
            }

            //agents add their ip to this project
            public void registerAgent(IPAddress ip)
            {
                agentsIP.Add(ip);
            }

            public List<IPAddress> AllAgents()
            {
                return agentsIP;
            }

            public IPAddress[] getThreeAgent()
        {

                IPAddress[] ips = new IPAddress[3];
                if(ips[0]!=null)
                ips[0] = agentsIP[0];
                if (ips[1] != null)
                ips[1] = agentsIP[1];
                if (ips[2] != null)
                ips[2] = agentsIP[2];
                return ips;
        }
        }
    }
}
